package org.tio.showcase.websocket.server;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.core.TioConfig;
import org.tio.showcase.ai.RobotChat;
import org.tio.showcase.dbUtil.MongoConst;
import org.tio.showcase.dbUtil.MongodbUtil;
import org.tio.showcase.dbUtil.RedisUtil;
import org.tio.utils.lock.SetWithLock;
import org.tio.websocket.common.WsResponse;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;

public class WsMsgSend {

    /**
     * 点对点发送
     */
    public static void pointToPoint(ChannelContext channelContext, String json){
        //channelContext.getToken()
        //String msg = channelContext.getClientNode().toString() + " 说：" + text;
        String msg;
        String toUserId;
        if(JSON.parseObject(json).containsKey("ustype")){   // layim UI
            if(JSON.parseObject(json).getString("id").equals("-1") || JSON.parseObject(json).getString("id").contains("-")){
                toUserId = JSON.parseObject(json).getString("userId");
                try {
                    String data = RobotChat.getRobotMsg(JSON.parseObject(json).getString("data"));
                    JSONObject object = JSONObject.parseObject(json);
                    object.put("data",data);
                    json = object.toString();
                }catch (Exception e){

                }
                msg = json;
            }else{
                msg = json;
                toUserId = JSON.parseObject(json).getString("id");
            }

        }else{  // 原版UI
            msg = "{userId:'" + channelContext.userid + "',data:'" + JSON.parseObject(json).getString("data") + "',type:'"+JSON.parseObject(json).getString("type")+"'}";
            toUserId = JSON.parseObject(json).getString("toUserId");
        }

        RedisUtil.setnx("Online:user_"+channelContext.userid,"这里可以缓存用户信息");
        RedisUtil.expire("Online:user_"+channelContext.userid,60*60);

        // 检查接收消息的用户是否在线,用户不在线将消息缓存在redis
        if(!RedisUtil.checkExists("Online:user_"+toUserId)){
            RedisUtil.rpush("OffLineMsg:user_"+toUserId+"_msg",msg);
        }else {
            //用tio-websocket，服务器发送到客户端的Packet都是WsResponse
            WsResponse wsResponse = WsResponse.fromText(msg, ShowcaseServerConfig.CHARSET);
            Tio.sendToUser(channelContext.tioConfig,toUserId,wsResponse);
        }
    }

    /**
     * 一对多发送
     * @param channelContext
     * @param json
     */
    public static void oneToMany(ChannelContext channelContext, String json){

        int count = Tio.getAll(channelContext.tioConfig).getObj().size();
//        Tio.groupCount()
        //获取某用户的ChannelContext集合
        String groupid;
        String msg;
        if(JSON.parseObject(json).containsKey("ustype")){
            groupid = JSON.parseObject(json).getString("id");
            msg = json;
        }else{
            groupid = JSON.parseObject(json).getString("groupId");
            msg = "{fromUserId:'" + channelContext.userid + "',data:'" + JSON.parseObject(json).getString("data") + "',type:'"+JSON.parseObject(json).getString("type")+"',groupId:'"+groupid+"'}";
        }

        Map map = new HashMap();
        map.put("groupId",groupid);
        List<Object> userid = MongodbUtil.findByPage(MongoConst.GROUP_USER,0,100,map);
        for (Object s:userid) {
            String uid = JSON.parseObject(s+"").getString("userId");
            if(!RedisUtil.checkExists("Online:user_"+uid)){
                RedisUtil.rpush("OffLineMsg:user_"+uid+"_group_msg",msg);
                RedisUtil.expire("OffLineMsg:user_"+uid+"_group_msg",60*60*24*7);    // 群消息缓存7 天，自动清除
            }
        }

        //用tio-websocket，服务器发送到客户端的Packet都是WsResponse
        WsResponse wsResponse = WsResponse.fromText(msg, ShowcaseServerConfig.CHARSET);
        //群发
        Tio.sendToGroup(channelContext.tioConfig, groupid, wsResponse);
    }

    // 绑定用户群组
    public static void bindUserToGroup(ChannelContext channelContext, String userId){
        // 一个用户有多个群组，循环查询相关群组id，并绑定
        Map map = new HashMap();
        map.put("userId",userId);
        // 由于 mongodb 我封装了一个公用方法，0 和 100 是分页的意思，我这里设置查询 100 条数据
        List<Object> groupid = MongodbUtil.findByPage(MongoConst.GROUP_USER,0,100,map);
        for (Object s:groupid) {
            JSONObject jsonObject = JSON.parseObject(s+"");
            System.out.println(jsonObject);
            Tio.bindGroup(channelContext,jsonObject.getString("groupId"));
        }
    }

    /**
     * 用户上线推送离线时的新消息
     * @param channelContext
     * @param
     */
    public static void Online_message_push(ChannelContext channelContext){
        ExecutorService executor = Executors.newFixedThreadPool(2);
        CompletableFuture<Object> future = CompletableFuture.supplyAsync(new Supplier<Object>() {
            @Override
            public synchronized Integer get() {
                System.out.println("===task start===");
                try {

                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("===task finish===");
                return 1;
            }
        }, executor);
        future.thenAccept(e -> Online_message_send(channelContext));

    }

    // 异步发送
    public static void Online_message_send(ChannelContext channelContext){
        String uid = channelContext.userid;
        List<Object> msg = (List<Object>) RedisUtil.lrange("OffLineMsg:user_"+uid+"_msg",0,-1);
        if(msg.size()>=1){
            RedisUtil.del("OffLineMsg:user_"+uid+"_msg");
            for (Object o:msg) {
                WsResponse wsResponse = WsResponse.fromText(o+"", ShowcaseServerConfig.CHARSET);
                Tio.sendToUser(channelContext.tioConfig,uid,wsResponse);
            }
        }
        // 群发
        List<Object> group_msg = (List<Object>) RedisUtil.lrange("OffLineMsg:user_"+uid+"_group_msg",0,-1);
        if(group_msg.size()>=1){
            RedisUtil.del("OffLineMsg:user_"+uid+"_group_msg");
            for (Object o:group_msg) {
                WsResponse wsResponse = WsResponse.fromText(o+"", ShowcaseServerConfig.CHARSET);
                Tio.sendToUser(channelContext.tioConfig,uid,wsResponse);
            }
        }
    }
}
